package com.vichat.user.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.vichat.common.cache.RedisHelper;
import com.vichat.common.constant.GlobalConstant;
import com.vichat.common.constant.I18nConstant;
import com.vichat.common.enums.RecordType;
import com.vichat.common.exception.ViChatException;
import com.vichat.common.util.DateUtil;
import com.vichat.common.util.I18NUtil;
import com.vichat.common.util.Md5Util;
import com.vichat.common.util.NumberUtils;
import com.vichat.common.vo.PageFilter;
import com.vichat.core.dao.BaseDaoI;
import com.vichat.user.entity.*;
import com.vichat.user.service.IUserCcsService;
import com.vichat.user.service.IUserService;
import com.vichat.user.util.CheckUtils;
import com.vichat.user.vo.AgentUseVO;
import com.vichat.user.vo.CcsUserOnlineVO;
import com.vichat.user.vo.UserCompanyVO;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.type.StringType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.net.URLDecoder;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by wangluyin on 16/9/17.
 */

@Service("userCcsServiceImpl")
public class UserCcsServiceImpl implements IUserCcsService {
    protected static final Logger logger = LoggerFactory.getLogger(UserCcsServiceImpl.class);
    ExecutorService tp = Executors.newCachedThreadPool();

    @Autowired
    private BaseDaoI<UserParty> partyDao;
    @Autowired
    private BaseDaoI<UserPartyCompany> partyCompanyDao;
    @Autowired
    private BaseDaoI<UserBasic> userDao;
    @Autowired
    private IUserService userService;
    @Autowired
    private BaseDaoI<CcsUser> ccsUserInfoDao;
    @Autowired
    private BaseDaoI<SysCcsBusiRecord> sysCcsBusiRecordDao;
    @Autowired
    private BaseDaoI<UserSecRoleRel> userSecRoleRelDao;
    @Autowired
    private BaseDaoI<UserPartyCompany> userPartyCompanyDao;
    @Autowired
    private BaseDaoI<UserOrg> orgDao;
    @Autowired
    private BaseDaoI<AgentUser> agentUserDao;
    @Autowired
    private BaseDaoI<AgentCompany> companyDao;
    @Autowired
    private BaseDaoI<RechargeRecord> rechargeRecordDao;
    @Autowired
    private BaseDaoI<SnResource> snResourceDao;
    @Autowired
    private BaseDaoI<AgentUserSecRoleRel> agentUserSecRoleRelDao;
    @Autowired
    private BaseDaoI<AppVersionFile> appVersionFileDao;

    private void updateUserOrgVersion(long orgId) {
        String hql = "update userdb.user_org set version = REPLACE(unix_timestamp(current_timestamp(3)),'.','') where org_id = " + orgId;
        orgDao.executeSql(hql);
    }

    public List<CcsUser> queryCcsUser(CcsUser ccsUser, PageFilter pageFilter) {
        String hql = "from CcsUser where state = 1";
        HashMap params = new HashMap();
        if (NumberUtils.isNotNullOrZero(ccsUser.getCcsUid())) {
            hql += " and ccsUid = :ccsUid";
            params.put("ccsUid", ccsUser.getCcsUid());
        }
        if (StringUtils.isNotBlank(ccsUser.getAccount())) {
            hql += " and account like :account";
            params.put("account", "%" + ccsUser.getAccount() + "%");
        }
        if (StringUtils.isNotBlank(ccsUser.getUname())) {
            hql += " and (uname like :uname or account like :uname)";
            params.put("uname", "%" + ccsUser.getUname() + "%");
        }
        return ccsUserInfoDao.find(hql, params, pageFilter.getPage(), pageFilter.getRows());
    }

    public long countCcsUser(CcsUser ccsUser) {
        String hql = "select count(*) from CcsUser where state = 1";
        HashMap params = new HashMap();
        if (NumberUtils.isNotNullOrZero(ccsUser.getCcsUid())) {
            hql += " and ccsUid = :ccsUid";
            params.put("ccsUid", ccsUser.getCcsUid());
        }
        if (StringUtils.isNotBlank(ccsUser.getAccount())) {
            hql += " and account like :account";
            params.put("account", "%" + ccsUser.getAccount() + "%");
        }
        if (StringUtils.isNotBlank(ccsUser.getUname())) {
            hql += " and (uname like :uname or account like :uname)";
            params.put("uname", "%" + ccsUser.getUname() + "%");
        }
        return ccsUserInfoDao.count(hql, params);
    }

    public void saveUserPartyCompany(UserPartyCompany company) {
        UserPartyCompany companyFDB = partyCompanyDao.get("from UserPartyCompany where state = 1 and partyId = " + company.getPartyId());
        companyFDB.setAuthNumber(company.getAuthNumber());
//        companyFDB.setFreeType(company.getFreeType());
        companyFDB.setCompanyAddress(company.getCompanyAddress());
        companyFDB.setCompanyCode(company.getCompanyCode());
        companyFDB.setUserName(company.getUserName());
        companyFDB.setCompanyName(company.getCompanyName());
        companyFDB.setTel(company.getTel());
        companyFDB.setFunction(company.getFunction());
        partyCompanyDao.save(companyFDB);
        RedisHelper.setPartyCompany(companyFDB.getPartyId(), JSONObject.toJSONString(companyFDB));
    }

    /**
     * 增加子账号
     *
     * @param user
     * @return
     */
    @Override
    public UserBasic saveUserBasicCcs(UserBasic user) throws ViChatException {
        if (NumberUtils.isNotNullOrZero(user.getUid())) {
            UserBasic userFDB = userService.queryUserBasicByUid(user.getUid());
            if (userFDB == null) {
                String errorMsg = I18NUtil.getMessage("error_userNotExist", null, Locale.getDefault());
                throw new ViChatException(I18nConstant.error_userNotExist, errorMsg);
            } else {
                userFDB.setUserName(user.getUserName());
                userFDB.setSex(user.getSex());
                userFDB.setPhone(user.getPhone());
                userDao.update(userFDB);
                RedisHelper.setUser(userFDB.getUid(), JSONObject.toJSONString(userFDB));

            }
        } else {
            if (StringUtils.isBlank(user.getPassword())) {
                user.setPassword("111111");
            }
            this.checkIsAccountExist(user);
            if (StringUtils.isNotBlank(user.getIccid())) {
                user.setTerminal(user.getIccid());
            }
            if (StringUtils.isNotBlank(user.getImei())) {
                user.setTerminal(user.getImei());
            }

            // 用户密码加密处理
            encryptUserBasic(user);
            UserOrg userOrg = null;
            if (NumberUtils.isNotNullOrZero(user.getOrgId())) {
                userOrg = userService.queryUserOrgByOrgId(user.getPartyId(), user.getOrgId());
            } else {
                userOrg = userService.getRootOrgByPartyId(user.getPartyId());
            }
            if (userOrg == null) {
                String errorMsg = I18NUtil.getMessage("error_orgNotExist", null, Locale.getDefault());
                throw new ViChatException(I18nConstant.error_orgNotExist, errorMsg);
            }
            user.setOrgId(userOrg.getOrgId());
            user.setOrgName(userOrg.getOrgName());
            user.setOrgCode(userOrg.getOrgCode());

            String jsonStr = RedisHelper.getPartyCompany(user.getPartyId());
            UserPartyCompany company = null;
            if (StringUtils.isNotBlank(jsonStr)) {
                company = JSONObject.parseObject(jsonStr, UserPartyCompany.class);
            } else {
                company = userService.getUserPartyCompanyByPartyId(user.getPartyId());
            }

            if (user.getUserType() == GlobalConstant.USER_TYPE_4) {
                CheckUtils.checkEffetiveDispatcherUserNumberMax(userService, 1);
            } else if (user.getUserType() == GlobalConstant.USER_TYPE_3) {
                CheckUtils.checkEffetiveTerminalUserNumberMax(userService, 1);
            }

            //判断sn账号是否可用
            if (user.getUserType() == GlobalConstant.USER_TYPE_3 && GlobalConstant.CHECK_TERMINAL_SN) {
                SnResource snResource = this.queryNotAssignSnResourceBySN(user.getImei());
                if (snResource == null) {
                    String errorMsg = I18NUtil.getMessage("error_orgNotExist", null, Locale.getDefault());
                    throw new ViChatException(I18nConstant.error_orgNotExist, errorMsg);
                } else {
                    snResource.setResState(0L);
                    snResource.setAgentId(null);
                    snResourceDao.update(snResource);
                }
            }

            //判断sn账号是否可用
            if (user.getUserType() == GlobalConstant.USER_TYPE_4 && GlobalConstant.CHECK_DISPATCHER_SN) {
                SnResource snResource = this.queryNotAssignSnResourceBySN(user.getImei());
                if (snResource == null) {
                    String errorMsg = I18NUtil.getMessage("error_snNotExist", null, Locale.getDefault());
                    throw new ViChatException(I18nConstant.error_snNotExist, errorMsg);
                } else {
                    snResource.setResState(0L);
                    snResourceDao.update(snResource);
                }
            }

            if (company.getFreeType() == GlobalConstant.FREE_TYPE_0) {
                user.setExpiredDate(DateUtil.getDateByString("2038-01-01", "yyyy-MM-dd"));
            } else {
                if (user.getExpiredDate() == null) {
                    user.setExpiredDate(DateUtil.getTodayTime("yyyy-MM-dd"));
                }
            }

            userDao.save(user);

            changeUserTypeRole(user);

            RedisHelper.setUser(user.getUid(), JSONObject.toJSONString(user));
        }
        return user;
    }

    private void changeUserTypeRole(UserBasic userBasic) {
        if (NumberUtils.isNotNullOrZero(userBasic.getUserType())) {
            if (userBasic.getUserType() == GlobalConstant.USER_TYPE_1) {
                userService.saveUserSecRoleRel(userBasic.getUid(), 1L);
            } else if (userBasic.getUserType() == GlobalConstant.USER_TYPE_4) {
                userService.saveUserSecRoleRel(userBasic.getUid(), 2L);
            }
        }
    }

    public Map<String, List<UserBasic>> batchCreateUser(List<UserBasic> users) {
        Map<String, List<UserBasic>> rtnMap = new HashMap<String, List<UserBasic>>();
        List<UserBasic> successList = new ArrayList<UserBasic>();
        List<UserBasic> failList = new ArrayList<UserBasic>();
        // 批量导入用户初始密码6个1

        for (UserBasic user : users) {
            user.setUid(null);// 清空uid
            user.setUserType(GlobalConstant.USER_TYPE_3);
            user.setPassword("111111");
            try {
                this.saveUserBasicCcs(user);
                successList.add(user);
            } catch (ViChatException e) {
                logger.error("batchCreateUser", e.getCode());
                user.setExt1(e.getCode());
                failList.add(user);
            } catch (Exception e) {
                logger.error("batchCreateUser", e);
                e.printStackTrace();
                failList.add(user);
            }
        }
        rtnMap.put("SUCCESS_LIST", successList);
        rtnMap.put("FAIL_LIST", failList);
        return rtnMap;
    }

    public Map<String, List<UserBasic>> batchUpdateUser(List<UserBasic> users) {
        Map<String, List<UserBasic>> rtnMap = new HashMap<String, List<UserBasic>>();
        List<UserBasic> successList = new ArrayList<UserBasic>();
        List<UserBasic> failList = new ArrayList<UserBasic>();

        for (UserBasic user : users) {
            try {
                this.saveUserBasicCcs(user);
                successList.add(user);
            } catch (Exception e) {
                logger.error("batchUpdateUser", e);
                e.printStackTrace();
                failList.add(user);
            }
        }
        rtnMap.put("SUCCESS_LIST", successList);
        rtnMap.put("FAIL_LIST", failList);
        return rtnMap;
    }

    /**
     * 对UserBasic进行密码加密处理
     *
     * @param user
     */
    protected void encryptUserBasic(UserBasic user) {
        String mim = Md5Util.Md5Encode(user.getPassword(), null);
        mim = Md5Util.Md5Encode(mim, null);
        user.setPassword(mim);
    }


    /**
     * 客服修改密码
     *
     * @param uid
     * @param newPassWord
     */
    public UserBasic ccsChgUserPass(long uid, String newPassWord) {
        UserBasic userFDB = userDao.get(UserBasic.class, uid);
        userFDB.setPassword(newPassWord);
        userDao.save(userFDB);
        // 刷新IM
        RedisHelper.setUser(uid, JSONObject.toJSONString(userFDB));
        return userFDB;
    }


    /**
     * 获取客服用户信息
     *
     * @param uid
     * @return
     */
    public CcsUser getCcsUserInfoById(long uid) {

        String jsonStr = RedisHelper.getCcsUser(uid);
        CcsUser ccsUser = null;
        if (StringUtils.isNotBlank(jsonStr)) {
            ccsUser = JSONObject.parseObject(jsonStr, CcsUser.class);
        } else {
            ccsUser = ccsUserInfoDao.get(CcsUser.class, uid);
            if (ccsUser != null) {
                RedisHelper.setCcsUser(ccsUser.getCcsUid(), JSONObject.toJSONString(ccsUser));
            }
        }
        return ccsUser;
    }

    /**
     * 获取客服用户信息
     *
     * @param account
     * @return
     */
    public CcsUser getCcsUserInfoByAccount(String account) {
        HashMap params = new HashMap();
        String hql = "from CcsUser where state = 1 and account = :account";
        params.put("account", account);
        List<CcsUser> ccsUserList = ccsUserInfoDao.find(hql, params);
        if (ccsUserList != null && !ccsUserList.isEmpty()) {
            return ccsUserList.get(0);
        }
        return null;
    }


    @Override
    public List<UserPartyCompany> queryUserCompanyCCS(UserPartyCompany company, UserBasic user, PageFilter pf, boolean isPrecision) throws Exception {
        String hql;
        HashMap params = new HashMap();
        if (StringUtils.isNotEmpty(user.getTerminal()) || StringUtils.isNotEmpty(user.getIccid())) {
            hql = "select distinct a from UserPartyCompany a , UserBasic b where a.state = 1 and b.state = 1 and a.partyId = b.partyId";
            if (!isPrecision) {
                hql += " and (b.terminal like :terminal or b.imei like :terminal or b.iccid like :terminal)";
                params.put("terminal", "%" + URLDecoder.decode(user.getTerminal(), "UTF-8") + "%");
            } else {
                hql += " and (b.terminal = :terminal or b.imei = :terminal or b.iccid = :terminal)";
                params.put("terminal", URLDecoder.decode(user.getTerminal(), "UTF-8"));
            }
        } else {
            hql = " from UserPartyCompany a  where a.state = 1 ";
        }
        if (StringUtils.isNotEmpty(company.getCompanyName())) {
            hql += " and a.companyName like :companyName";
            params.put("companyName", "%" + URLDecoder.decode(company.getCompanyName(), "UTF-8") + "%");
        }
        if (NumberUtils.isNotNullOrZero(company.getPartyId())) {
            hql += " and a.partyId = :partyId";
            params.put("partyId", company.getPartyId());
        }
        if (NumberUtils.isNotNull(company.getFreeType())) {
            hql += " and a.freeType = :freeType";
            params.put("freeType", company.getFreeType());
        }
        if (NumberUtils.isNotNullOrZero(company.getAgentId())) {
            hql += " and a.agentId = :agentId";
            params.put("agentId", company.getAgentId());
        } else {
            if (NumberUtils.isNull(company.getAgentId())) {
                hql += " and a.agentId is NULL";
            }
        }

        return partyCompanyDao.find(hql, params, pf.getPage(), pf.getRows());
    }

    /**
     * 查询组织数量
     *
     * @return
     */
    public Long countUserCompanyCCS(UserPartyCompany company, UserBasic user, boolean isPrecision) throws Exception {
        String hql;
        HashMap params = new HashMap();
        if (StringUtils.isNotEmpty(user.getTerminal()) || StringUtils.isNotEmpty(user.getIccid())) {
            hql = " from UserPartyCompany a , UserBasic b where a.state = 1 and b.state = 1 and a.partyId = b.partyId";
            if (!isPrecision) {
                hql += " and (b.terminal like :terminal or b.imei like :terminal or b.iccid like :terminal)";
                params.put("terminal", "%" + URLDecoder.decode(user.getTerminal(), "UTF-8") + "%");
            } else {
                hql += " and (b.terminal = :terminal or b.imei = :terminal or b.iccid = :terminal)";
                params.put("terminal", URLDecoder.decode(user.getTerminal(), "UTF-8"));
            }

        } else {
            hql = " from UserPartyCompany a  where a.state = 1 ";
        }
        if (StringUtils.isNotEmpty(company.getCompanyName())) {
            hql += " and a.companyName like :companyName";
            params.put("companyName", "%" + URLDecoder.decode(company.getCompanyName(), "UTF-8") + "%");
        }
        if (NumberUtils.isNotNullOrZero(company.getPartyId())) {
            hql += " and a.partyId = :partyId";
            params.put("partyId", company.getPartyId());
        }
        if (NumberUtils.isNotNull(company.getFreeType())) {
            hql += " and a.freeType = :freeType";
            params.put("freeType", company.getFreeType());
        }
        if (NumberUtils.isNotNullOrZero(company.getAgentId())) {
            hql += " and a.agentId = :agentId";
            params.put("agentId", company.getAgentId());
        } else {
            if (NumberUtils.isNull(company.getAgentId())) {
                hql += " and a.agentId is NULL";
            }
        }

        return partyCompanyDao.count("select count(distinct a) " + hql, params);
    }

    /**
     * 保存操作日志
     *
     * @param user
     * @param type
     * @param opedUid
     * @param opedUserName
     * @param opedInfo
     * @param remark
     * @throws Exception
     */
    public void saveSysCcsBusiRecord(CcsUser user, RecordType type, long opedUid, String opedUserName, String opedInfo, String remark) {
        try {
            SysCcsBusiRecord busiRecord = new SysCcsBusiRecord();
            if (user != null) {
                busiRecord.setUid(user.getCcsUid());
                busiRecord.setUserName(user.getUname());
            }
            busiRecord.setOpedType(type.getCode());
            busiRecord.setOpedUid(opedUid);
            busiRecord.setOpedUserName(opedUserName);
            busiRecord.setOpedInfo(opedInfo);
            busiRecord.setRemark(remark);
            sysCcsBusiRecordDao.save(busiRecord);
        } catch (Exception e) {
            logger.error("保存操作日志失败");
        }
    }

    public UserBasic getUserBasicByTerminal(String terminal) {
        String hql = "from UserBasic where state = 1 and terminal = :terminal";
        HashMap params = new HashMap();
        params.put("terminal", terminal);
        List<UserBasic> users = userDao.find(hql, params);
        if (users != null && users.size() > 0) {
            return users.get(0);
        }
        return null;
    }

    /**
     * 判断账号是否已存在
     *
     * @param userBasic
     */
    public void checkIsAccountExist(UserBasic userBasic) throws ViChatException {
        if (StringUtils.isNotBlank(userBasic.getTerminal())) {
            if (userService.isTerminalExist(userBasic.getTerminal())) {
                String errorMsg = I18NUtil.getMessage("error_accountIsExist", null, Locale.getDefault());
                throw new ViChatException(I18nConstant.error_accountIsExist, errorMsg);
            }
        }
        if (StringUtils.isNotBlank(userBasic.getIccid())) {
            if (userService.isIccidExist(userBasic.getIccid())) {
                String errorMsg = I18NUtil.getMessage("error_ICCIDIsExist", null, Locale.getDefault());
                throw new ViChatException(I18nConstant.error_ICCIDIsExist, errorMsg);
            }
        }
        if (StringUtils.isNotBlank(userBasic.getImei())) {
            if (userService.isImeiExist(userBasic.getImei())) {
                String errorMsg = I18NUtil.getMessage("error_IMEIIsExist", null, Locale.getDefault());
                throw new ViChatException(I18nConstant.error_IMEIIsExist, errorMsg);
            }
        }

        if (StringUtils.isBlank(userBasic.getTerminal()) && StringUtils.isBlank(userBasic.getIccid()) && StringUtils.isBlank(userBasic.getImei())) {
            String errorMsg = I18NUtil.getMessage("error_parameter", null, Locale.getDefault());
            throw new ViChatException(I18nConstant.error_parameter, errorMsg);
        }
    }

    public void registerPartyCompany(UserParty party, UserPartyCompany company, UserBasic user) throws ViChatException {
        this.checkIsAccountExist(user);
        //保存企业
        party.setPartyName(company.getCompanyName());
        //企业服务码
        String partyKey = UUID.randomUUID().toString().replaceAll("-", "").replaceAll("[a-zA-Z]", "").substring(0, 8);
        party.setPartyKey(partyKey);
        partyDao.save(party);
        RedisHelper.setParty(party.getPartyId(), JSONObject.toJSONString(party));
        //创建公司
        company.setPartyId(party.getPartyId());
        if (company.getFreeType() == null) {
            company.setFreeType(GlobalConstant.FREE_TYPE_1);// 收费，按用户失效期收费
            company.setAuthMonth(0L);
        }
        if (StringUtils.isNotBlank(company.getContactName())) {
            company.setUserName(company.getContactName());
        }
        userPartyCompanyDao.save(company);
        RedisHelper.setPartyCompany(party.getPartyId(), JSONObject.toJSONString(company));
        //创建默认组织
        UserOrg org = new UserOrg();
        org.setOrgName(company.getCompanyName());
        org.setPartyId(party.getPartyId());
        String orgCode = this.getOrgCode(org);
        org.setOrgCode(orgCode);
        orgDao.save(org);
        this.updateUserOrgVersion(org.getOrgId());
        RedisHelper.setOrg(org.getOrgId(), JSONObject.toJSONString(org));
        encryptAccount(user);

        //保存登陆账号
        user.setUserType(GlobalConstant.USER_USER_TYPE_OWNER_1);
        user.setPartyId(party.getPartyId());
        user.setOrgId(org.getOrgId());
        user.setOrgCode(orgCode);
        user.setUserName(company.getCompanyName());
        if (company.getFreeType() == GlobalConstant.FREE_TYPE_0) {
            user.setExpiredDate(DateUtil.getDateByString("2038-01-01", "yyyy-MM-dd"));
        } else {
            if (user.getExpiredDate() == null) {
                user.setExpiredDate(DateUtil.getTodayTime("yyyy-MM-dd"));
            }
        }
        userDao.save(user);
        userService.updateUserBasicVersion(user.getUid());

        //增加对应关系
        UserSecRoleRel roleRole = new UserSecRoleRel();
        roleRole.setRoid(1L);
        roleRole.setUid(user.getUid());
        roleRole.setState(1L);
        roleRole.setUpdateTime(new Date());
        roleRole.setCreateTime(new Date());
        userSecRoleRelDao.save(roleRole);

        RedisHelper.setUser(user.getUid(), JSONObject.toJSONString(user));
    }

    /**
     * 对账号进行密码加密处理
     *
     * @param account
     */
    private void encryptAccount(UserBasic account) {
        String mim = Md5Util.Md5Encode(account.getPassword(), null);
        mim = Md5Util.Md5Encode(mim, null);
        account.setPassword(mim);
    }

    /**
     * 获取组织编号
     *
     * @param org
     * @return
     */
    private String getOrgCode(UserOrg org) {
        StringBuilder sql = new StringBuilder();
        if (NumberUtils.isNullOrZero(org.getParentId())) {
            sql.append("select LPAD(max(org_code+1),6,0) ID from user_org where parent_id=0");
        } else {
            sql.append("select concat(MIN(t.org_code),substr(concat('00',substr(MAX(t.org_code),length(MIN(t.org_code))+1,3)+1),length(concat('00',substr(MAX(t.org_code),length(MIN(t.org_code))+1,3)+1))-2,3)) ID from user_org t where t.org_code like '");
            sql.append(org.getOrgCode()).append("%'");
        }
        String orgCode = (String) orgDao.executeQueryBasic(sql.toString(), "ID", StringType.INSTANCE);
        if (StringUtils.isBlank(orgCode)) {
            orgCode = "000001";
        }
        return orgCode;
    }

    @Override
    public void registerAgentCompany(AgentUser user, AgentCompany company) throws ViChatException {
        checkIsAgentAccountExist(user.getAccount());
        company.setLeafLevel(1L);
        company.setAgentCode(this.getAgentCode(company));
        company.setParentId(0L);
        company.setCreateTime(new Date());
        company.setUpdateTime(new Date());
        company.setAuthMonth(0L);
        companyDao.save(company);
        RedisHelper.setAgentCompany(company.getAgentId(), JSONObject.toJSONString(company));

        encryptAccount(user);

        //保存登陆账号
        user.setUserName(company.getCompanyName());
        user.setUserType(GlobalConstant.USER_USER_TYPE_OWNER_1);
        user.setAgentId(company.getAgentId());
        user.setCreateTime(new Date());
        user.setUpdateTime(new Date());
        agentUserDao.save(user);


        AgentUserSecRoleRel roleRole = new AgentUserSecRoleRel();
        roleRole.setRoid(1L);
        roleRole.setAgentUid(user.getAgentUid());
        roleRole.setState(1L);
        roleRole.setUpdateTime(new Date());
        roleRole.setCreateTime(new Date());
        agentUserSecRoleRelDao.save(roleRole);

        RedisHelper.setAgentUser(user.getAgentUid(), JSONObject.toJSONString(user));
    }


    /**
     * 对账号进行密码加密处理
     *
     * @param account
     */
    private void encryptAccount(AgentUser account) {
        String mim = Md5Util.Md5Encode(account.getPassword(), null);
        mim = Md5Util.Md5Encode(mim, null);
        account.setPassword(mim);
    }

    /**
     * 获取组织编号
     *
     * @param company
     * @return
     */
    private String getAgentCode(AgentCompany company) {
        StringBuilder sql = new StringBuilder();
        if (NumberUtils.isNullOrZero(company.getParentId())) {
            sql.append("select LPAD(max(agent_code+1),6,0) ID from ccsdb.agent_company where parent_id=0");
        } else {
            sql.append("select concat(MIN(t.agent_code),substr(concat('00',substr(MAX(t.agent_code),length(MIN(t.agent_code))+1,3)+1),length(concat('00',substr(MAX(t.agent_code),length(MIN(t.agent_code))+1,3)+1))-2,3)) ID from ccsdb.agent_company t where t.agent_code like '").append(company.getAgentCode() + "%'");
        }
        String orgCode = (String) companyDao.executeQueryBasic(sql.toString(), "ID", StringType.INSTANCE);
        if (StringUtils.isBlank(orgCode)) {
            orgCode = "000001";
        }
        return orgCode;
    }

    @Override
    public List<AgentCompany> queryAgentCompany(AgentUser user, AgentCompany company, PageFilter pf) throws Exception {
        String hql;
        HashMap params = new HashMap();
        if (StringUtils.isNotEmpty(user.getAccount())) {
            hql = "select distinct a from AgentCompany a , AgentUser b where a.state = 1 and b.state = 1 and a.agentId = b.agentId and b.userType=1";
            if (StringUtils.isNotEmpty(user.getAccount())) {
                hql += " and b.account like :account";
                params.put("account", "%" + URLDecoder.decode(user.getAccount(), "UTF-8") + "%");
            }
        } else {
            hql = " from AgentCompany a  where a.state = 1 ";
        }
        if (StringUtils.isNotEmpty(company.getCompanyName())) {
            hql += " and a.companyName like :companyName";
            params.put("companyName", "%" + URLDecoder.decode(company.getCompanyName(), "UTF-8") + "%");
        }
        if (NumberUtils.isNotNullOrZero(company.getAgentId())) {
            hql += " and a.agentId = :agentId";
            params.put("agentId", company.getAgentId());
        }
        if (NumberUtils.isNotNullOrZero(company.getParentId())) {
            hql += " and a.parentId = :parentId";
            params.put("parentId", company.getParentId());
        }
        if (NumberUtils.isNotNullOrZero(company.getLeafLevel())) {
            hql += " and a.leafLevel = :leafLevel";
            params.put("leafLevel", company.getLeafLevel());
        }

        return companyDao.find(hql, params, pf.getPage(), pf.getRows());
    }

    public long countAgentCompany(AgentUser user, AgentCompany company) throws Exception {
        String hql;
        HashMap params = new HashMap();
        if (StringUtils.isNotEmpty(user.getAccount())) {
            hql = " from AgentCompany a , AgentUser b where a.state = 1 and b.state = 1 and a.agentId = b.agentId and b.userType=1";
            if (StringUtils.isNotEmpty(user.getAccount())) {
                hql += " and b.account like :account";
                params.put("account", "%" + URLDecoder.decode(user.getAccount(), "UTF-8") + "%");
            }
        } else {
            hql = " from AgentCompany a  where a.state = 1 ";
        }
        if (StringUtils.isNotEmpty(company.getCompanyName())) {
            hql += " and a.companyName like :companyName";
            params.put("companyName", "%" + URLDecoder.decode(company.getCompanyName(), "UTF-8") + "%");
        }
        if (NumberUtils.isNotNullOrZero(company.getAgentId())) {
            hql += " and a.agentId = :agentId";
            params.put("agentId", company.getAgentId());
        }
        if (NumberUtils.isNotNullOrZero(company.getParentId())) {
            hql += " and a.parentId = :parentId";
            params.put("parentId", company.getParentId());
        }
        if (NumberUtils.isNotNullOrZero(company.getLeafLevel())) {
            hql += " and a.leafLevel = :leafLevel";
            params.put("leafLevel", company.getLeafLevel());
        }
        return companyDao.count("select count(distinct a.agentId) " + hql, params);
    }

    public AgentUser getAgentUserByAgentId(long agentId, long userType) {
        String hql = "from AgentUser where state = 1 and agentId = :agentId and userType = :userType";
        HashMap params = new HashMap();
        params.put("agentId", agentId);
        params.put("userType", userType);
        List<AgentUser> list = agentUserDao.find(hql, params);
        if (list != null && list.size() > 0) {
            return list.get(0);
        }
        return null;
    }

    @Override
    public AgentCompany getAgentCompanyByAgentId(long agentId) {
        String jsonStr = RedisHelper.getAgentCompany(agentId);
        AgentCompany companyFDB = null;
        if (StringUtils.isNotBlank(jsonStr)) {
            companyFDB = JSONObject.parseObject(jsonStr, AgentCompany.class);
        } else {
            companyFDB = companyDao.get(AgentCompany.class, agentId);
            if (companyFDB != null) {
                RedisHelper.setAgentCompany(companyFDB.getAgentId(), JSONObject.toJSONString(companyFDB));
            }
        }
        return companyFDB;
    }

    public AgentCompany queryAgentCompanyByAgentId(long agentId) {
        AgentCompany companyFDB = companyDao.get(AgentCompany.class, agentId);
        if (companyFDB != null) {
            RedisHelper.setAgentCompany(companyFDB.getAgentId(), JSONObject.toJSONString(companyFDB));
        }
        return companyFDB;
    }

    @Override
    public AgentUser getAgentUserByUid(long uid) {
        return agentUserDao.get(AgentUser.class, uid);
    }

    public void saveAgentCompany(AgentCompany company) {
        AgentCompany companyFDB = companyDao.get("from AgentCompany where state = 1 and agentId = " + company.getAgentId());
        if (companyFDB != null) {
            if (StringUtils.isNotBlank(company.getAdminName())) {
                companyFDB.setAdminName(company.getAdminName());
            }
            companyFDB.setAddress(company.getAddress());
            companyFDB.setEmail(company.getEmail());
            companyFDB.setMobile(company.getMobile());
            companyFDB.setUrl(company.getUrl());
            if (StringUtils.isNotBlank(company.getRemark())) {
                companyFDB.setRemark(company.getRemark());
            }
            companyFDB.setUpdateTime(new Date());
            companyDao.update(companyFDB);
            RedisHelper.setAgentCompany(companyFDB.getAgentId(), JSONObject.toJSONString(companyFDB));
        }
    }

    /**
     * 客服修改代理商密码
     *
     * @param uid
     * @param newPassWord
     */
    public AgentUser ccsChgAgentUserPass(long uid, String newPassWord) {
        AgentUser userFDB = agentUserDao.get(AgentUser.class, uid);
        userFDB.setPassword(newPassWord);
        agentUserDao.save(userFDB);
        // 刷新IM
        RedisHelper.setAgentUser(uid, JSONObject.toJSONString(userFDB));
        return userFDB;
    }

    /**
     * 客服修改代理商密码
     *
     * @param uid
     * @param newPassWord
     */
    public CcsUser ccsChgCcsUserPass(long uid, String newPassWord) {
        CcsUser userFDB = ccsUserInfoDao.get(CcsUser.class, uid);
        userFDB.setPassword(newPassWord);
        ccsUserInfoDao.save(userFDB);
        // 刷新IM
        RedisHelper.setCcsUser(uid, JSONObject.toJSONString(userFDB));
        return userFDB;
    }

    public List<AgentUser> queryAgentUsers(AgentUser user, PageFilter pf) throws Exception {
        String hql = "from AgentUser where state = 1";
        Map<String, Object> params = new HashMap<String, Object>();
        return agentUserDao.find(hql + agentUserWhereHql(user, params), params, pf.getPage(), pf.getRows());
    }

    public Long countAgentUsers(AgentUser user) throws Exception {
        String hql = "select count(*) from AgentUser where state = 1";
        Map<String, Object> params = new HashMap<String, Object>();
        return agentUserDao.count(hql + agentUserWhereHql(user, params), params);
    }

    /**
     * 拼装用户条件
     *
     * @param bean
     * @param params
     * @return
     */
    private String agentUserWhereHql(AgentUser bean, Map<String, Object> params) throws Exception {
        String hql = "";
        if (bean != null) {
            if (NumberUtils.isNotNullOrZero(bean.getAgentUid())) {
                hql += " and agentUid = :agentUid";
                params.put("agentUid", bean.getAgentUid());
            }

            if (StringUtils.isNotBlank(bean.getUserName())) {
                hql += " and (userName like :userName or  account like :userName or tel like :userName )";
                params.put("userName", "%" + URLDecoder.decode(bean.getUserName(), "UTF-8") + "%");
            }

            if (StringUtils.isNotBlank(bean.getAccount())) {
                hql += " and account like :account ";
                params.put("account", "%" + bean.getAccount() + "%");
            }
            if (StringUtils.isNotBlank(bean.getTel())) {
                hql += " and tel like :tel";
                params.put("tel", "%" + bean.getTel() + "%");
            }
            if (NumberUtils.isNotNullOrZero(bean.getUserType())) {
                hql += " and userType = :userType";
                params.put("userType", bean.getUserType());
            }
            if (NumberUtils.isNotNullOrZero(bean.getAgentId())) {
                hql += " and agentId = :agentId";
                params.put("agentId", bean.getAgentId());
            }
        }
        return hql;
    }

    /**
     * 保存或者修改用户信息
     *
     * @param user
     * @return
     */
    public AgentUser saveAgentUser(AgentUser user) throws ViChatException {

        if (NumberUtils.isNullOrZero(user.getAgentUid())) {//新增
            if (StringUtils.isBlank(user.getPassword())) {
                user.setPassword("111111");
            }
            checkAgentUserAccountExist(user.getAccount());
            String mim = Md5Util.Md5Encode(Md5Util.Md5Encode(user.getPassword(), null), null);
            user.setPassword(mim);
            user.setUserType(GlobalConstant.USER_TYPE_2);
            agentUserDao.save(user);
            RedisHelper.setAgentUser(user.getAgentUid(), JSONObject.toJSONString(user));
            return user;
        } else {//修改
            AgentUser userFDB = getAgentUserByUid(user.getAgentUid());
            if (userFDB == null) {
//                throw new Exception("uid:" + user.getUid() + " 的用户不存在");
                String errorMsg = I18NUtil.getMessage("RoomApiController.getRooms.error_userNotExist", null, Locale.getDefault());
                throw new ViChatException(I18nConstant.error_userNotExist, errorMsg);
            }

            //企业级管理员不可修改用户类型，也不可被改成企业级管理员
//            if (userFDB.getUserType() != GlobalConstant.USER_TYPE_1 && user.getUserType() != GlobalConstant.USER_TYPE_1) {
//                userFDB.setUserType(user.getUserType());
//            }

            userFDB.setUserName(user.getUserName());
            userFDB.setTel(user.getTel());
            userFDB.setEmail(user.getEmail());
            userFDB.setSex(user.getSex());
            userFDB.setUpdateTime(new Date());
            agentUserDao.update(userFDB);
            RedisHelper.setAgentUser(userFDB.getAgentUid(), JSONObject.toJSONString(userFDB));
            return userFDB;

        }
    }

    /**
     * 判断账号是否已存在
     *
     * @param account
     */
    public void checkAgentUserAccountExist(String account) throws ViChatException {
        AgentUser agentUser = getAgentUserByAccount(account);
        if (agentUser != null) {
            String errorMsg = I18NUtil.getMessage("UserServiceImpl.checkIsAccountExist.error_AccountIsExist", null, Locale.CHINA);
            throw new ViChatException(I18nConstant.error_accountIsExist, errorMsg);
        }
    }

    @Override
    public AgentUser getAgentUserByAccount(String account) {
        String hql = "from AgentUser where state = 1 and account = :account";
        HashMap params = new HashMap();
        params.put("account", account);
        List<AgentUser> users = agentUserDao.find(hql, params);
        if (users != null && users.size() > 0) {
            return users.get(0);
        }
        return null;
    }

    @Override
    public Map<String, List<AgentUser>> batchUpdateAgentUser(List<AgentUser> users) {
        Map<String, List<AgentUser>> rtnMap = new HashMap<String, List<AgentUser>>();
        List<AgentUser> successList = new ArrayList<AgentUser>();
        List<AgentUser> failList = new ArrayList<AgentUser>();

        for (AgentUser user : users) {
            try {
                this.saveAgentUser(user);
                successList.add(user);
            } catch (Exception e) {
                logger.error("batchUpdateUser", e);
                e.printStackTrace();
                failList.add(user);
            }
        }
        rtnMap.put("SUCCESS_LIST", successList);
        rtnMap.put("FAIL_LIST", failList);
        return rtnMap;
    }

    public Map<String, List<AgentUser>> batchCreateAgentUser(List<AgentUser> users) {
        Map<String, List<AgentUser>> rtnMap = new HashMap<String, List<AgentUser>>();
        List<AgentUser> successList = new ArrayList<AgentUser>();
        List<AgentUser> failList = new ArrayList<AgentUser>();
        // 批量导入用户初始密码6个1

        for (AgentUser user : users) {
            user.setAgentUid(null);// 清空uid
            user.setUserType(GlobalConstant.USER_TYPE_2);
            user.setPassword("111111");
            try {
                this.saveAgentUser(user);
                successList.add(user);
            } catch (Exception e) {
                logger.error("batchCreateUser", e);
                e.printStackTrace();
                failList.add(user);
            }
        }
        rtnMap.put("SUCCESS_LIST", successList);
        rtnMap.put("FAIL_LIST", failList);
        return rtnMap;
    }


    public void updateExpiredDate(CcsUser sessionUser, AgentCompany agentCompany, Integer monthNumber, String record) throws ViChatException {
        if (agentCompany != null) {
            AgentUser agentUserFDB = this.getAgentUserByAgentId(agentCompany.getAgentId(), GlobalConstant.USER_TYPE_1);
            if (agentUserFDB == null) {
                String errorMsg = I18NUtil.getMessage("error_userNotExist", null, Locale.getDefault());
                throw new ViChatException(I18nConstant.error_userNotExist, errorMsg);
            }

            this.saveRechargeRecordAgentOut(sessionUser, agentCompany, monthNumber, record);
            this.saveRechargeRecordAgentIn(sessionUser, agentCompany, monthNumber, record);

            //修改进账企业余额
            if (NumberUtils.isNotNullOrZero(agentCompany.getAuthMonth())) {
                agentCompany.setAuthMonth(agentCompany.getAuthMonth() + monthNumber);
            } else {
                agentCompany.setAuthMonth((long) monthNumber);
            }

            companyDao.update(agentCompany);
            RedisHelper.setAgentCompany(agentCompany.getAgentId(), JSONObject.toJSONString(agentCompany));

        } else {
            String errorMsg = I18NUtil.getMessage("error_agentCompanyNotExist", null, Locale.getDefault());
            throw new ViChatException(I18nConstant.error_agentCompanyNotExist, errorMsg);
        }
    }

    //记录流水 出账
    private void saveRechargeRecordAgentOut(CcsUser sessionUser, AgentCompany agentCompany, Integer monthNumber, String remark) throws ViChatException {
        //记录流水
        RechargeRecord rechargeRecord = new RechargeRecord();
        rechargeRecord.setObj2PartyId(agentCompany.getAgentId());
        rechargeRecord.setObj2PartyName(agentCompany.getCompanyName());
        rechargeRecord.setObj2Type(2L);
        rechargeRecord.setBusiType(3L);
        rechargeRecord.setObj1Uid(sessionUser.getCcsUid());
        rechargeRecord.setObj1Uname(sessionUser.getUname());
        rechargeRecord.setObj1Type(1L);
        rechargeRecord.setChgValue((long) (0 - monthNumber));
        rechargeRecord.setRemark(remark);
        rechargeRecord.setCreateTime(new Date());
        rechargeRecord.setExt1(remark);
        rechargeRecord.setChgType(2L);
        rechargeRecordDao.save(rechargeRecord);
    }

    //记录流水 进账
    private void saveRechargeRecordAgentIn(CcsUser sessionUser, AgentCompany agentCompany, Integer monthNumber, String remark) throws ViChatException {
        //记录流水 进账
        RechargeRecord rechargeRecordIn = new RechargeRecord();
        rechargeRecordIn.setObj1PartyId(agentCompany.getAgentId());
        rechargeRecordIn.setObj1PartyName(agentCompany.getCompanyName());
        rechargeRecordIn.setObj1Type(2L);
        rechargeRecordIn.setBusiType(3L);
        rechargeRecordIn.setObj2Uid(sessionUser.getCcsUid());
        rechargeRecordIn.setObj2Uname(sessionUser.getUname());
        rechargeRecordIn.setObj2Type(1L);
        if (NumberUtils.isNullOrZero(agentCompany.getAuthMonth())) {
            rechargeRecordIn.setChgBefore("0");
            rechargeRecordIn.setChgAfter(String.valueOf(monthNumber));
        } else {
            rechargeRecordIn.setChgBefore(String.valueOf(agentCompany.getAuthMonth()));
            rechargeRecordIn.setChgAfter(String.valueOf(agentCompany.getAuthMonth() + monthNumber));
        }
        rechargeRecordIn.setChgValue((long) monthNumber);
        rechargeRecordIn.setRemark(remark);
        rechargeRecordIn.setCreateTime(new Date());
        rechargeRecordIn.setExt1(remark);
        rechargeRecordIn.setChgType(1L);
        rechargeRecordDao.save(rechargeRecordIn);
    }


    public void updateUserExpiredDate(CcsUser sessionUser, UserBasic userBasic, Integer monthNumber) throws ViChatException {
        UserPartyCompany company = userService.getUserPartyCompanyByPartyId(userBasic.getPartyId());
        if (company != null) {

            rechargeRecordUserIn(sessionUser, userBasic, company, monthNumber);

            rechargeRecordUserOut(sessionUser, userBasic, company, monthNumber);

            //更新所剩额度
        } else {
            String errorMsg = I18NUtil.getMessage("error_agentCompanyNotExist", null, Locale.getDefault());
            throw new ViChatException(I18nConstant.error_agentCompanyNotExist, errorMsg);
        }
    }

    private void rechargeRecordUserIn(CcsUser sessionUser, UserBasic userFDB, UserPartyCompany company, Integer monthNumber) {
        Date oldExpiredDate = userFDB.getExpiredDate();
        Date newExpiredDate = DateUtil.addMonth(userFDB.getExpiredDate(), monthNumber);


        RechargeRecord rechargeRecord = new RechargeRecord();
        rechargeRecord.setObj1PartyId(company.getPartyId());
        rechargeRecord.setObj1PartyName(company.getCompanyName());
        rechargeRecord.setObj1Type(3L);
        rechargeRecord.setObj1Uid(userFDB.getUid());
        rechargeRecord.setObj1Uname(userFDB.getUserName());
        rechargeRecord.setObj2Type(1L);
        rechargeRecord.setObj2Uid(sessionUser.getCcsUid());
        rechargeRecord.setObj2Uname(sessionUser.getUname());
        rechargeRecord.setBusiType(1L);
        rechargeRecord.setChgBefore(DateUtil.getFormattedDate(oldExpiredDate));
        rechargeRecord.setChgAfter(DateUtil.getFormattedDate(newExpiredDate));
        rechargeRecord.setChgValue((long) monthNumber);
        rechargeRecord.setChgType(1L);
        rechargeRecord.setCreateTime(new Date());
        rechargeRecordDao.save(rechargeRecord);

        userFDB.setExpiredDate(newExpiredDate);
        userDao.update(userFDB);
        RedisHelper.setUser(userFDB.getUid(), JSONObject.toJSONString(userFDB));
    }

    private void rechargeRecordUserOut(CcsUser sessionUser, UserBasic userFDB, UserPartyCompany company, Integer monthNumber) {
        RechargeRecord rechargeRecord = new RechargeRecord();
        rechargeRecord.setObj2PartyId(company.getPartyId());
        rechargeRecord.setObj2PartyName(company.getCompanyName());
        rechargeRecord.setObj2Type(3L);
        rechargeRecord.setObj2Uid(userFDB.getUid());
        rechargeRecord.setObj2Uname(userFDB.getUserName());
        rechargeRecord.setObj1Type(1L);
        rechargeRecord.setObj1Uid(sessionUser.getCcsUid());
        rechargeRecord.setObj1Uname(sessionUser.getUname());
        rechargeRecord.setBusiType(1L);
        rechargeRecord.setChgValue((long) (0 - monthNumber));
        rechargeRecord.setChgType(2L);
        rechargeRecord.setCreateTime(new Date());

        rechargeRecordDao.save(rechargeRecord);
    }


    /**
     * 判断账号是否已存在
     *
     * @param account
     */
    public void checkIsAgentAccountExist(String account) throws ViChatException {
        AgentUser agentUser = getAgentUserByAccount(account);
        if (agentUser != null) {
            String errorMsg = I18NUtil.getMessage("UserServiceImpl.checkIsAccountExist.error_AccountIsExist", null, Locale.CHINA);
            throw new ViChatException(I18nConstant.error_accountIsExist, errorMsg);
        }
    }

    public CcsUserOnlineVO getUserOnlineView() throws Exception {
        AgentCompany queryAgentCompany = new AgentCompany();
        long allAgentNum = this.countAgentCompany(new AgentUser(), queryAgentCompany);
        queryAgentCompany.setLeafLevel(1l);
        long oneLevelAgentNum = this.countAgentCompany(new AgentUser(), queryAgentCompany);

        UserBasic queryUserBean = new UserBasic();
        long allUserNum = userService.countUserBasics(queryUserBean, false);
        long effetiveDispatcherUser = userService.countEffetiveDispatcherUser();
        long effetiveTermianlUser = userService.countEffetiveTermianlUser();

        UserPartyCompany queryCompany = new UserPartyCompany();
        queryCompany.setAgentId(0l);
        queryCompany.setFreeType(null);
        long companyNum = this.countUserCompanyCCS(queryCompany, new UserBasic(), false);

        UserCompanyVO queryUserCompanyBean = new UserCompanyVO();
        long expiringUserNum = userService.countExpiringUser(30, queryUserCompanyBean).longValue();

        long maxDispatcherAuthNumber = GlobalConstant.MAX_DISPATCHER_AUTH_NUMBER;
        long maxTerminalAuthNumber = GlobalConstant.MAX_TERMINAL_AUTH_NUMBER;

        CcsUserOnlineVO ccsUserOnlineVO = new CcsUserOnlineVO();
        ccsUserOnlineVO.setAllAgentNum(allAgentNum);
        ccsUserOnlineVO.setAllUserNum(allUserNum);
        ccsUserOnlineVO.setCompanyNum(companyNum);
        ccsUserOnlineVO.setEffectiveDispatcherUserNum(effetiveDispatcherUser);
        ccsUserOnlineVO.setEffectiveTerminalUserNum(effetiveTermianlUser);
        ccsUserOnlineVO.setExpiringUserNum(expiringUserNum);
        ccsUserOnlineVO.setOneLevelAgentNum(oneLevelAgentNum);
        ccsUserOnlineVO.setMaxDispatcherAuthNum(maxDispatcherAuthNumber);
        ccsUserOnlineVO.setMaxTerminalAuthNum(maxTerminalAuthNumber);

        return ccsUserOnlineVO;
    }

    public List<RechargeRecord> queryRechargeRecord(RechargeRecord rechargeRecord, PageFilter pageFilter) throws Exception {
        String hql = "from RechargeRecord where 1=1 ";
        HashMap params = new HashMap();
        return rechargeRecordDao.find(hql + rechargeRecordWhereHql(rechargeRecord, params) + " order by rcdId desc ", params, pageFilter.getPage(), pageFilter.getRows());
    }

    public long countRechargeRecord(RechargeRecord rechargeRecord) throws Exception {
        String hql = "select count(*) from RechargeRecord where 1=1 ";
        HashMap params = new HashMap();
        return rechargeRecordDao.count(hql + rechargeRecordWhereHql(rechargeRecord, params), params);
    }


    /**
     * 拼装用户条件
     *
     * @param bean
     * @param params
     * @return
     */
    private String rechargeRecordWhereHql(RechargeRecord bean, Map<String, Object> params) throws Exception {
        String hql = "";
        if (bean != null) {
            if (NumberUtils.isNotNullOrZero(bean.getObj1PartyId())) {
                hql += " and obj1PartyId = :obj1PartyId";
                params.put("obj1PartyId", bean.getObj1PartyId());
            }

            if (StringUtils.isNotBlank(bean.getObj1PartyName())) {
                hql += " and obj1PartyName like :obj1PartyName";
                params.put("obj1PartyName", "%" + URLDecoder.decode(bean.getObj1PartyName(), "UTF-8") + "%");
            }
            if (NumberUtils.isNotNullOrZero(bean.getObj2PartyId())) {
                hql += " and obj2PartyId = :obj2PartyId";
                params.put("obj2PartyId", bean.getObj2PartyId());
            }

            if (StringUtils.isNotBlank(bean.getObj2PartyName())) {
                hql += " and obj2PartyName like :obj2PartyName";
                params.put("obj2PartyName", "%" + URLDecoder.decode(bean.getObj2PartyName(), "UTF-8") + "%");
            }

            if (NumberUtils.isNotNullOrZero(bean.getObj1Type())) {
                hql += " and obj1Type = :obj1Type";
                params.put("obj1Type", bean.getObj1Type());
            }
            if (NumberUtils.isNotNullOrZero(bean.getObj2Type())) {
                hql += " and obj2Type = :obj2Type";
                params.put("obj2Type", bean.getObj2Type());
            }
            if (NumberUtils.isNotNullOrZero(bean.getObj2Uid())) {
                hql += " and obj2Uid = :obj2Uid";
                params.put("obj2Uid", bean.getObj2Uid());
            }
            if (StringUtils.isNotBlank(bean.getObj2Uname())) {
                hql += " and obj2Uname like :obj2Uname";
                params.put("obj2Uname", "%" + URLDecoder.decode(bean.getObj2Uname(), "UTF-8") + "%");
            }
            if (NumberUtils.isNotNullOrZero(bean.getObj1Uid())) {
                hql += " and obj1Uid = :obj1Uid";
                params.put("obj1Uid", bean.getObj1Uid());
            }
            if (StringUtils.isNotBlank(bean.getObj1Uname())) {
                hql += " and obj1Uname like :obj1Uname";
                params.put("obj1Uname", "%" + URLDecoder.decode(bean.getObj1Uname(), "UTF-8") + "%");
            }
            if (NumberUtils.isNotNullOrZero(bean.getChgType())) {
                hql += " and chgType = :chgType";
                params.put("chgType", bean.getChgType());
            }
            if (NumberUtils.isNotNullOrZero(bean.getBusiType())) {
                hql += " and busiType = :busiType";
                params.put("busiType", bean.getBusiType());
            }
            if (bean.getStartDate() != null) {
                hql += " and createTime >= :startDate";
                params.put("startDate", bean.getStartDate());
            }
            if (bean.getEndDate() != null) {
                hql += " and createTime <= :endDate";
                params.put("endDate", bean.getEndDate());
            }


        }
        return hql;
    }

    @Override
    public void setRechargeRecordRemark(long logId, String remark) throws ViChatException {
        RechargeRecord rechargeRecordFDB = this.getRechargeRecordById(logId);
        if (rechargeRecordFDB != null) {
            rechargeRecordFDB.setExt1(remark);
            rechargeRecordDao.update(rechargeRecordFDB);
        } else {
            String errorMsg = I18NUtil.getMessage("error_recordNotExist", null, Locale.getDefault());
            throw new ViChatException(I18nConstant.error_recordNotExist, errorMsg);
        }
    }

    public RechargeRecord getRechargeRecordById(long logId) {
        return rechargeRecordDao.get(RechargeRecord.class, logId);
    }

    public List<AgentUseVO> queryAgentCompanyShort(String name, Long parentId, PageFilter pageFilter) throws ViChatException {
        HashMap params = new HashMap<>();
        String hql = "select agent_id as agentId,company_name as companyName from ccsdb.agent_company where state = 1";
        if (StringUtils.isNotBlank(name)) {
            hql += " and company_name like :companyName";
            params.put("companyName", "%" + name + "%");
        }
        if (parentId != null) {
            hql += " and parent_id = :parentId";
            params.put("parentId", parentId);
        }
        return companyDao.findVoBySql(hql, params, AgentUseVO.class, pageFilter.getPage(), pageFilter.getRows());
    }

    public List<UserPartyCompany> queryUserPartyCompanyShort(String name, long agentId, PageFilter pageFilter) throws ViChatException {
        HashMap params = new HashMap<>();
        String hql = "select partyId,companyName from UserPartyCompany where state = 1 ";
        if (NumberUtils.isNotNullOrZero(agentId)) {
            hql += " and agentId = :agentId";
            params.put("agentId", agentId);
        }
        if (StringUtils.isNotBlank(name)) {
            hql += " and companyName like :companyName";
            params.put("companyName", "%" + name + "%");
        }
        return partyCompanyDao.find(hql, params, pageFilter.getPage(), pageFilter.getRows());
    }

    public List<UserBasic> queryUserBasicShort(String name, long partyId, PageFilter pageFilter) throws ViChatException {
        HashMap params = new HashMap<>();
        String hql = "select uid,userName from UserBasic where state = 1 and partyId = :partyId ";
        params.put("partyId", partyId);
        if (StringUtils.isNotBlank(name)) {
            hql += " and userName like :userName";
            params.put("userName", "%" + name + "%");
        }
        return userDao.find(hql, params, pageFilter.getPage(), pageFilter.getRows());
    }

    public void assginSN(List<SnResource> snResourceList, Long agentId) throws ViChatException {
        for (SnResource snResource : snResourceList) {
            snResource.setAgentId(agentId);
            this.saveSnResource(snResource);
        }
    }

    public SnResource querySnResourceBySN(String sn) {
        HashMap params = new HashMap<>();
        String hql = "from SnResource where state = 1 and sn = :sn";
        params.put("sn", sn);
        List<SnResource> snResourceList = snResourceDao.find(hql, params);
        if (snResourceList != null && !snResourceList.isEmpty()) {
            return snResourceList.get(0);
        }
        return null;
    }

    public SnResource queryNotAssignSnResourceBySN(String sn) {
        HashMap params = new HashMap<>();
        String hql = "from SnResource where state = 1 and resState = 1 and sn = :sn ";
        params.put("sn", sn);
        List<SnResource> snResourceList = snResourceDao.find(hql, params);
        if (snResourceList != null && !snResourceList.isEmpty()) {
            return snResourceList.get(0);
        }
        return null;
    }

    public SnResource saveSnResource(SnResource snResource) throws ViChatException {
        if (NumberUtils.isNullOrZero(snResource.getSnId())) {
            SnResource snResourceFDB = this.querySnResourceBySN(snResource.getSn());
            if (snResourceFDB != null) {
                String errorMsg = I18NUtil.getMessage("error_snIsExist", null, Locale.getDefault());
                throw new ViChatException(I18nConstant.error_snIsExist, errorMsg);
            }
            snResourceDao.save(snResource);
        } else {
            SnResource snResourceFDB = this.querySnResourceBySnId(snResource.getSnId());
            if (snResourceFDB == null) {
                String errorMsg = I18NUtil.getMessage("error_snNotExist", null, Locale.getDefault());
                throw new ViChatException(I18nConstant.error_snNotExist, errorMsg);
            }
            if (snResource.getAgentId() != null) {
                snResourceFDB.setAgentId(snResource.getAgentId());
            }
            snResourceFDB.setResState(snResource.getResState());
            snResourceDao.update(snResourceFDB);
        }
        return snResource;
    }

    public Map<String, List<SnResource>> batchSaveSnResources(List<SnResource> snResourceList) {
        Map<String, List<SnResource>> rtnMap = new HashMap<String, List<SnResource>>();
        List<SnResource> successList = new ArrayList<SnResource>();
        List<SnResource> failList = new ArrayList<SnResource>();
        // 批量导入用户初始密码6个1

        for (SnResource resource : snResourceList) {
            try {
                this.saveSnResource(resource);
                successList.add(resource);
            } catch (Exception e) {
                logger.error("batchSaveResources", e);
                e.printStackTrace();
                failList.add(resource);
            }
        }
        rtnMap.put("SUCCESS_LIST", successList);
        rtnMap.put("FAIL_LIST", failList);
        return rtnMap;
    }

    public List<SnResource> querySnResource(SnResource snResource, PageFilter pageFilter) {
        String hql = "from SnResource where state = 1 ";
        HashMap params = new HashMap();
        return snResourceDao.find(hql + snResourceWhereHql(snResource, params), params, pageFilter.getPage(), pageFilter.getRows());
    }

    public long countSnResource(SnResource snResource) {
        String hql = "select count(*) from SnResource where state = 1 ";
        HashMap params = new HashMap();
        return snResourceDao.count(hql + snResourceWhereHql(snResource, params), params);
    }

    private String snResourceWhereHql(SnResource snResource, HashMap params) {
        String hql = "";
        if (NumberUtils.isNotNullOrZero(snResource.getSnId())) {
            hql += " and snId = :snId";
            params.put("snId", snResource.getSnId());
        }
        if (NumberUtils.isNotNullOrZero(snResource.getAgentId())) {
            hql += " and agentId = :agentId";
            params.put("agentId", snResource.getAgentId());
        }
        if (snResource.getResState() != null) {
            hql += " and resState = :resState";
            params.put("resState", snResource.getResState());
        }
        if (StringUtils.isNotBlank(snResource.getSn())) {
            hql += " and sn like :sn";
            params.put("sn", "%" + snResource.getSn() + "%");
        }
        if (StringUtils.isNotBlank(snResource.getSnType())) {
            hql += " and snType like :snType";
            params.put("snType", snResource.getSnType() + "%");
        }
        return hql;
    }

    public SnResource querySnResourceBySnId(long snId) {
        List<SnResource> snResourceList = snResourceDao.find("from SnResource where state = 1 and snId = " + snId);
        if (snResourceList != null && !snResourceList.isEmpty()) {
            return snResourceList.get(0);
        }
        return null;

    }

    public void delSnResource(SnResource snResource) {
        snResource.setState(0L);
        snResourceDao.update(snResource);
    }

    public void deleteAgent(long agentId) {
        AgentCompany agentCompany = this.queryAgentCompanyByAgentId(agentId);
        if (agentCompany != null) {
            agentCompany.setState(0L);
            companyDao.update(agentCompany);
        }
    }

    public void deleteAgentUser(Long agentUid) throws ViChatException {
        AgentUser agentUser = this.getAgentUserByUid(agentUid);
        if (agentUser != null) {
            agentUser.setState(0L);
            agentUserDao.update(agentUser);
        } else {
            String errorMsg = I18NUtil.getMessage("error_userNotExist", null, Locale.getDefault());
            throw new ViChatException(I18nConstant.error_userNotExist, errorMsg);
        }
    }

    public void deleteCcsUser(Long ccsUid) throws ViChatException {
        CcsUser ccsUser = this.getCcsUserInfoById(ccsUid);
        if (ccsUser != null) {
            ccsUser.setState(0L);
            ccsUserInfoDao.update(ccsUser);
        } else {
            String errorMsg = I18NUtil.getMessage("error_userNotExist", null, Locale.getDefault());
            throw new ViChatException(I18nConstant.error_userNotExist, errorMsg);
        }
    }

    public CcsUser saveCcsUser(CcsUser user) throws ViChatException {
        if (NumberUtils.isNotNullOrZero(user.getCcsUid())) {
            CcsUser ccsUserFDB = this.getCcsUserInfoById(user.getCcsUid());
            if (ccsUserFDB == null) {
                String errorMsg = I18NUtil.getMessage("error_userNotExist", null, Locale.getDefault());
                throw new ViChatException(I18nConstant.error_userNotExist, errorMsg);
            }
            ccsUserFDB.setUname(user.getUname());
            ccsUserFDB.setPhone(user.getPhone());
            ccsUserFDB.setSex(user.getSex());
            ccsUserInfoDao.update(ccsUserFDB);
            RedisHelper.setCcsUser(user.getCcsUid(), JSONObject.toJSONString(ccsUserFDB));
        } else {
            if (StringUtils.isBlank(user.getPassword())) {
                user.setPassword("111111");
            }
            checkCcsUserAccountExist(user.getAccount());
            String mim = Md5Util.Md5Encode(Md5Util.Md5Encode(user.getPassword(), null), null);
            user.setPassword(mim);
            ccsUserInfoDao.save(user);
            RedisHelper.setCcsUser(user.getCcsUid(), JSONObject.toJSONString(user));
        }
        return null;
    }

    /**
     * 判断账号是否已存在
     *
     * @param account
     */
    public void checkCcsUserAccountExist(String account) throws ViChatException {
        CcsUser ccsUser = this.getCcsUserInfoByAccount(account);
        if (ccsUser != null) {
            String errorMsg = I18NUtil.getMessage("error_accountIsExist", null, Locale.CHINA);
            throw new ViChatException(I18nConstant.error_accountIsExist, errorMsg);
        }
    }

    public void saveAppVersionFile(AppVersionFile file) {
        if (NumberUtils.isNotNullOrZero(file.getFileId())) {
            appVersionFileDao.update(file);
        } else {
            file.setFileState(2L);
            appVersionFileDao.save(file);
        }
    }

    public void startVersionFile(long fileId) {
        AppVersionFile fileFDB = this.getAppVersionFileByFileId(fileId);
        if (fileFDB != null) {
            fileFDB.setFileState(1L);
            appVersionFileDao.update(fileFDB);
        }
    }

    public AppVersionFile getAppVersionFileByFileId(long fileId) {
        return appVersionFileDao.get(AppVersionFile.class, fileId);
    }

    public AppVersionFile getAppVersionFileByVersionCode(long versionCode, String pkgName) {
        String hql = "from AppVersionFile where pkgName = :pkgName and versionCode = :versionCode";
        HashMap params = new HashMap();
        params.put("pkgName", pkgName);
        params.put("versionCode", versionCode);

        List<AppVersionFile> fileList = appVersionFileDao.find(hql, params);
        if (fileList != null && !fileList.isEmpty()) {
            return fileList.get(0);
        }
        return null;
    }

    public AppVersionFile getStartAppVersionFileByPkgName(String pkgName) {
        String hql = "from AppVersionFile where pkgName = :pkgName and fileState = 1";
        HashMap params = new HashMap();
        params.put("pkgName", pkgName);

        List<AppVersionFile> fileList = appVersionFileDao.find(hql, params);
        if (fileList != null && !fileList.isEmpty()) {
            return fileList.get(0);
        }

        return null;
    }

    public List<AppVersionFile> queryAppVersionFile(AppVersionFile file, PageFilter pageFilter) {
        String hql = "from AppVersionFile where state = 1";
        HashMap params = new HashMap();
        return appVersionFileDao.find(hql + queryAppVersionFileWhereHql(file, params) + " order By fileId desc", params, pageFilter.getPage(), pageFilter.getRows());
    }

    public long countAppVersionFile(AppVersionFile file) {
        String hql = "select count(*) from AppVersionFile where state = 1";
        HashMap params = new HashMap();
        return appVersionFileDao.count(hql + queryAppVersionFileWhereHql(file, params) + " order By fileId desc", params);
    }

    private String queryAppVersionFileWhereHql(AppVersionFile file, HashMap params) {
        String hql = "";
        if (StringUtils.isNotBlank(file.getPkgName())) {
            hql += " and pkgName like :pkgName";
            params.put("pkgName", "%" + file.getPkgName() + "%");
        }
        if (NumberUtils.isNotNullOrZero(file.getVersionCode())) {
            hql += " and versionCode = :versionCode";
            params.put("versionCode", file.getVersionCode());
        }
        if (NumberUtils.isNotNullOrZero(file.getFileState())) {
            hql += " and fileState = :fileState";
            params.put("fileState", file.getFileState());
        }
        if (StringUtils.isNotBlank(file.getFileName())) {
            hql += " and fileName like :fileName";
            params.put("fileName", "%" + file.getFileName() + "%");
        }
        if (StringUtils.isNotBlank(file.getVersionName())) {
            hql += " and versionName like :versionName";
            params.put("versionName", "%" + file.getVersionName() + "%");
        }
        return hql;
    }

    public void delAppVersionFile(long fileId) {
        AppVersionFile file = this.getAppVersionFileByFileId(fileId);
        if (file != null) {
            file.setState(0L);
            appVersionFileDao.update(file);
        }
    }

    public void updateStartedVersionFileByPkgName(String pkgName) {
        String sql = "update userdb.app_version_file set file_state = 3 where file_state = 1 and pkg_name = '" + pkgName + "'";
        appVersionFileDao.executeSql(sql);
    }

    public void updateCompanyExpiredDate(CcsUser sessionUser, UserPartyCompany company, Integer monthNumber, String record) throws ViChatException {
        if (company != null) {

            this.saveRechargeRecordCompanyOut(sessionUser, company, monthNumber, record);
            this.saveRechargeRecordCompanyIn(sessionUser, company, monthNumber, record);

            //修改进账企业余额
            if (NumberUtils.isNotNullOrZero(company.getAuthMonth())) {
                company.setAuthMonth(company.getAuthMonth() + monthNumber);
            } else {
                company.setAuthMonth((long) monthNumber);
            }

            userPartyCompanyDao.update(company);
            RedisHelper.setPartyCompany(company.getPartyId(), JSONObject.toJSONString(company));

        } else {
            String errorMsg = I18NUtil.getMessage("error_agentCompanyNotExist", null, Locale.CHINA);
            throw new ViChatException(I18nConstant.error_agentCompanyNotExist, errorMsg);
        }
    }

    //记录流水 出账
    private void saveRechargeRecordCompanyOut(CcsUser sessionUser, UserPartyCompany company, Integer monthNumber, String remark) throws ViChatException {
        //记录流水
        RechargeRecord rechargeRecord = new RechargeRecord();
        rechargeRecord.setObj2PartyId(company.getPartyId());
        rechargeRecord.setObj2PartyName(company.getCompanyName());
        rechargeRecord.setObj2Type(4L);
        rechargeRecord.setBusiType(4L);
        rechargeRecord.setObj1Uid(sessionUser.getCcsUid());
        rechargeRecord.setObj1Uname(sessionUser.getUname());
        rechargeRecord.setObj1Type(1L);
        rechargeRecord.setChgValue((long) (0 - monthNumber));
        rechargeRecord.setRemark(remark);
        rechargeRecord.setCreateTime(new Date());
        rechargeRecord.setExt1(remark);
        rechargeRecord.setChgType(1L);
        rechargeRecordDao.save(rechargeRecord);
    }

    //记录流水 进账
    private void saveRechargeRecordCompanyIn(CcsUser sessionUser, UserPartyCompany company, Integer monthNumber, String remark) throws ViChatException {
        //记录流水 进账
        RechargeRecord rechargeRecordIn = new RechargeRecord();
        rechargeRecordIn.setObj1PartyId(company.getPartyId());
        rechargeRecordIn.setObj1PartyName(company.getCompanyName());
        rechargeRecordIn.setObj1Type(4L);
        rechargeRecordIn.setBusiType(4L);
        rechargeRecordIn.setObj2Uid(sessionUser.getCcsUid());
        rechargeRecordIn.setObj2Uname(sessionUser.getUname());
        rechargeRecordIn.setObj2Type(1L);
        if (NumberUtils.isNullOrZero(company.getAuthMonth())) {
            rechargeRecordIn.setChgBefore("0");
            rechargeRecordIn.setChgAfter(String.valueOf(monthNumber));
        } else {
            rechargeRecordIn.setChgBefore(String.valueOf(company.getAuthMonth()));
            rechargeRecordIn.setChgAfter(String.valueOf(company.getAuthMonth() + monthNumber));
        }
        rechargeRecordIn.setChgValue((long) monthNumber);
        rechargeRecordIn.setRemark(remark);
        rechargeRecordIn.setCreateTime(new Date());
        rechargeRecordIn.setExt1(remark);
        rechargeRecordIn.setChgType(2L);
        rechargeRecordDao.save(rechargeRecordIn);
    }
}
